#include <driver/view/msg.h>
#include <driver/view/screen.h>
#include <driver/view/mouse.h>
#include <driver/view/env.h>
#include <lib/stddef.h>
#include <lib/list.h>
#include <os/msgpool.h>
#include <os/debug.h>

//global msgpool
msgpool_t *view_global_msgpool ;

int ViewGlobalMsgInit()
{
    //alloc and create
    view_global_msgpool = MsgpoolCreate(sizeof(view_msg_t), VIEW_MSGPOOL_MSG_NUM * 2);
    if (!view_global_msgpool)
        return -1;
    return 0;
}

void ViewGlobalMsgExit()
{
    if (view_global_msgpool)
        MsgpoolDestroy(view_global_msgpool);
    view_global_msgpool = NULL;
}

//dispatch keyboard msg
int ViewDispatchKeycodeMsg(view_msg_t *msg)
{
    view_t *view = ViewEnvGetActivity();
    
    //KPrint("[view msg] dispatch keyboard msg to ivew %d\n",view->id);

    int val = -1;
    if (view)
    {
        view_msg_t m;
        ViewMsgHeader(&m, msg->id, view->id);
        ViewMsgData(&m, msg->data0, msg->data1, 0, 0);
        val = ViewPutMsg(view, &m, VIEW_MSG_NOWAIT); //send to view
    }
    return 0;
}

int ViewDispatchMouseMsg(view_msg_t *msg)
{
    if (!ViewEnvFilterMouseMsg(msg))
        return 0;

    list_t *list_head = ViewGetShowList();
    view_t *view=NULL;

    //KPrint("[view msg] dispatch mouse msg\n");

    //from top to bottom view traversal
    list_traversal_all_own_to_pre(view, list_head, list)
    {
        //KPrint("view id %d z %d\n",view->id,view->z);
        
        //skip mouse view
        if (view == view_mouse.view)
        {
            continue;
        }

        int local_mx, local_my;
        local_mx = msg->data0 - view->x;
        local_my = msg->data1 - view->y;

        if (local_mx >= 0 && local_mx < view->width && local_my >= 0 && local_my < view->height)
        {
            //mouse left button down,just activate view
            if (ViewMsgGetId(msg) == VIEW_MSG_MOUSE_LBTN_DOWN)
            {
                ViewEnvTryActivity(view);
            }
            //mouse drag
            ViewEnvDoMouseHover(view, msg, local_mx, local_my);
            /*if (!ViewEnvDoResize(view, msg, local_mx, local_my))
            {
                KPrint("[view msg] env: do resize ok\n");
                return 0;
            }*/
            ViewEnvDoDrag(view, msg, local_mx, local_my);
            //send msg
            view_msg_t m;
            ViewMsgHeader(&m, msg->id, view->id);
            ViewMsgData(&m, local_mx, local_my, msg->data0, msg->data1);
            ViewPutMsg(view, &m, VIEW_MSG_NOWAIT);
            return 0;
       } 
    }
    return -1;
}


//dispatch a msg to targe view
int ViewDispatchTargeMsg(view_msg_t *msg)
{
    if (msg->targe == VIEW_TARGE_NONE)
        return -1;

    view_t *view = ViewFindById(msg->targe);
    if (!view)
        return -1;
    //send msg to targe view
    return ViewPutMsg(view, msg, VIEW_MSG_NOWAIT);
}